package com.sl.core.engine.boot;

import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import com.sl.core.domain.dto.DataSourceConfigDTO;
import com.sl.core.engine.log.ProcessLogLayout;
import com.sl.core.engine.log.ProcessLoggingEventListener;
import com.sl.core.engine.log.ProcessLogChannelInterfaceFactory;
import com.sl.core.engine.log.ProcessLoggingBuffer;
import com.sl.core.engine.plugin.ProcessPluginLoaderManager;
import com.sl.core.engine.plugin.ProcessPluginRegistry;
import com.sl.core.engine.plugin.domain.PluginDecorate;
import com.sl.core.engine.meta.valuemeta.ValueMetaArray;
import com.sl.core.engine.meta.valuemeta.ValueMetaObject;
import lombok.SneakyThrows;
import org.apache.commons.compress.utils.Lists;
import org.apache.hop.core.Const;
import org.apache.hop.core.HopEnvironment;
import org.apache.hop.core.auth.AuthenticationProviderPluginType;
import org.apache.hop.core.compress.CompressionPluginType;
import org.apache.hop.core.config.plugin.ConfigPluginType;
import org.apache.hop.core.database.DatabaseMetaPlugin;
import org.apache.hop.core.database.DatabasePluginType;
import org.apache.hop.core.encryption.HopTwoWayPasswordEncoder;
import org.apache.hop.core.encryption.TwoWayPasswordEncoderPluginType;
import org.apache.hop.core.extension.ExtensionPointPluginType;
import org.apache.hop.core.logging.HopLogStore;
import org.apache.hop.core.logging.IHopLoggingEventListener;
import org.apache.hop.core.logging.LoggingBuffer;
import org.apache.hop.core.logging.Slf4jLoggingEventListener;
import org.apache.hop.core.plugins.*;
import org.apache.hop.core.row.value.ValueMetaPlugin;
import org.apache.hop.core.row.value.ValueMetaPluginType;
import org.apache.hop.execution.plugin.ExecutionInfoLocationPluginType;
import org.apache.hop.execution.sampler.ExecutionDataSamplerPluginType;
import org.apache.hop.pipeline.engine.PipelineEnginePluginType;
import org.apache.hop.workflow.engine.WorkflowEnginePluginType;

import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Map;

public class ProcessBoot {

    /**
     * 初始化环境。 此方法将尝试配置 简单的JNDI， 通过简单地调用init(true)。
     */
    @SneakyThrows
    public static void init() {
        //避免重复启动
        //取消控制台日志
        System.setProperty(Const.HOP_DEFAULT_DATE_FORMAT, "yyyy-MM-dd HH:mm:ss");
        System.getProperties().put(Const.HOP_DISABLE_CONSOLE_LOGGING, "Y");
        System.setProperty(Const.HOP_EMPTY_STRING_DIFFERS_FROM_NULL, "Y");
        System.setProperty(Const.HOP_PASSWORD_ENCODER_PLUGIN, "sl");
        TwoWayPasswordEncoderPluginType.getInstance().registerCustom(HopTwoWayPasswordEncoder.class, null, "sl", "", "", null);

        HopEnvironment.init();

        removeSlf4jLog();

        ReflectUtil.setFieldValue(HopLogStore.getInstance(), "appender", ProcessLoggingBuffer.getInstance());

        HopLogStore.getAppender().setLayout(new ProcessLogLayout());
        HopLogStore.setLogChannelFactory(new ProcessLogChannelInterfaceFactory());
//        KettleLogStore.init();
        ProcessLoggingEventListener processLoggingEventListener = new ProcessLoggingEventListener();
        HopLogStore.getAppender().addLoggingEventListener(processLoggingEventListener);

        removeSystemPlugins();

        //扩展数组
        ValueMetaPlugin valueMetaPlugin = AnnotationUtil.getAnnotation(ValueMetaArray.class, ValueMetaPlugin.class);
        ValueMetaPluginType.getInstance().registerCustom(ValueMetaArray.class, "", valueMetaPlugin.id(), valueMetaPlugin.name(), valueMetaPlugin.description(), "");

        //扩展对象
        valueMetaPlugin = AnnotationUtil.getAnnotation(ValueMetaObject.class, ValueMetaPlugin.class);
        ValueMetaPluginType.getInstance().registerCustom(ValueMetaObject.class, "", valueMetaPlugin.id(), valueMetaPlugin.name(), valueMetaPlugin.description(), "");


//        DatabaseMetaPlugin step = AnnotationUtil.getAnnotation(LatestH2DatabaseMeta.class, DatabaseMetaPlugin.class);
//        DatabasePluginType.getInstance().registerCustom(LatestH2DatabaseMeta.class, null, step.type(), step.typeDescription(), step.typeDescription(), null);

        //开始查找插件 并注册
        Map<String, List<PluginDecorate>> loader = ProcessPluginLoaderManager.INSTANCE.loader();
        ProcessPluginRegistry.INSTANCE.registry(loader);
    }

    private static void removeSystemPlugins() {

        List<Class> pluginTypes = Lists.newArrayList();
        pluginTypes.add(PipelineEnginePluginType.class);
        pluginTypes.add(ConfigPluginType.class);
        pluginTypes.add(ActionPluginType.class);
        pluginTypes.add(HopServerPluginType.class);
        pluginTypes.add(ExtensionPointPluginType.class);
        pluginTypes.add(ExecutionInfoLocationPluginType.class);
        pluginTypes.add(CompressionPluginType.class);
        pluginTypes.add(AuthenticationProviderPluginType.class);
        pluginTypes.add(TransformPluginType.class);
        pluginTypes.add(WorkflowEnginePluginType.class);
        pluginTypes.add(ExecutionDataSamplerPluginType.class);
        pluginTypes.add(TwoWayPasswordEncoderPluginType.class);

        for (Class pluginType : pluginTypes) {
            List<Plugin> plugins = PluginRegistry.getInstance().getPlugins(pluginType);
            //把自带的插件移除掉 没有用
            for (Plugin plugin : plugins) {
                PluginRegistry.getInstance().removePlugin(pluginType, plugin);
            }
        }
    }

    private static void removeSlf4jLog() {
        LoggingBuffer appender = HopLogStore.getAppender();
        Object eventListenerList = ReflectUtil.getFieldValue(appender, "eventListeners");
        if (ObjectUtil.isNull(eventListenerList)) {
            return;
        }
        List<IHopLoggingEventListener> eventListeners = (List<IHopLoggingEventListener>) eventListenerList;
        for (IHopLoggingEventListener eventListener : eventListeners) {
            if (eventListener instanceof Slf4jLoggingEventListener) {
                appender.removeLoggingEventListener(eventListener);
            }
        }
    }
}
